use std::time::Duration;

use log::info;
use smol::channel::bounded;
use smol::prelude::*;
use smol::Timer;

pub async fn run() {
    let (s, r) = bounded::<()>(1);
    let timeout = || async {
        Timer::after(Duration::from_secs(1)).await;
        Ok(())
    };

    let task = smol::spawn(async move {
        let mut i = 1;
        loop {
            if r.recv().or(timeout()).await.is_err() {
                break;
            }

            info!(
                "{:?} > super loop: Even though I'm in an infinite loop, you can still cancel me!",
                std::thread::current().id()
            );
            let r = r.clone();
            smol::spawn(async move {
                loop {
                    if r.recv().or(timeout()).await.is_err() {
                        break;
                    }
                    info!(
                        "{:?} > {} loop: I'm independent of the super loop!",
                        std::thread::current().id(),
                        i
                    );
                }
            })
            .detach();
            i += 1;
        }
    });

    Timer::after(Duration::from_secs(5)).await;
    info!("{:?} > Start cancel!", std::thread::current().id());
    s.close();
    task.cancel().await;
    info!("{:?} > Cancel done!", std::thread::current().id());
    Timer::after(Duration::from_secs(3)).await;
}
